//
// Created by lz on 3/13/21.
//

#ifndef MYWEBLIB_NET_CONNECTOR_H_
#define MYWEBLIB_NET_CONNECTOR_H_

#include "base/noncopyable.h"

#include "net/InetAddress.h"

#include <functional>
#include <memory>

namespace lzweb
{
	namespace net
	{
		class Channel;
		class EventLoop;

		class Connector : noncopyable,
						  public std::enable_shared_from_this<Connector>
		{
		 public:
			using NewConnectionCallback = std::function<void(int sockfd)>;

			Connector(EventLoop* loop, const InetAddress& serverAddr);
			~Connector();

			void setNewConnectionCallback(const NewConnectionCallback cb)
			{
				newConnectionCallback_ = cb;
			}

			void start();
			void restart();
			void stop();

			const InetAddress& serverAddress() const { return serverAddr_; }


		 private:
			enum States { kDisconnected, kConnecting, kConnected};
			static const int kMaxRetryDelayMs = 30 * 1000;
			static const int kInitRetryDelayMs = 500;

			void setState( States s) { state_ = s; }
			void startInLoop();
			void stopInLoop();
			void connect();
			void connecting(int sockfd);
			void handleWrite();
			void handleError();
			void retry(int sockfd);
			int removeAndResetChannel();
			void resetChannel();

			EventLoop* loop_;
			InetAddress serverAddr_;
			bool connect_;   //atomic
			States state_;	 // FIXME: use atomic variable
			std::unique_ptr<Channel> channel_;
			NewConnectionCallback newConnectionCallback_;
			int retryDelayMs_;
		};
	} // namespace net
} // namespace lzweb





#endif //MYWEBLIB_NET_CONNECTOR_H_
